import type { Metadata } from 'next'; import Link from 'next/link'; import { notFound } from 'next/navigation'; import { AdminTitle, Bool, JsonPre, Mono, StatusChip } from '@/components/admin/ui'; import { TierBadge } from '@/components/ui/badges'; import { DataTable, EmptyRow, Td, Th } from '@/components/ui/data-table'; import { KeyValue } from '@/components/ui/key-value'; import { LiveAgo } from '@/components/ui/live'; import { Unavailable } from '@/components/ui/unavailable'; import { adminApi, load, requireAdmin } from '@/lib/admin/admin-api'; import type { AdminSnapshotRow } from '@/lib/admin/types'; import { fmtBytes, fmtDateTime, fmtInt, num } from '@/lib/format'; import { routes } from '@/lib/site'; export const metadata: Metadata = { title: 'Document', robots: { index: false, follow: false } }; export const dynamic = 'force-dynamic'; export default async function AdminDocumentPage({ params }: { params: Promise<{ id: string }> }) { await requireAdmin(); const { id } = await params; const res = await load(adminApi.document(id)); if (!res.ok && res.error.startsWith('404')) notFound(); if (!res.ok) { return ( <> ); } const d = res.data; const snaps: AdminSnapshotRow[] = Array.isArray(d.snapshots) ? d.snapshots : []; const meta = { ...(d.meta ?? {}) } as Record; delete meta.raw_path; delete meta.text_path; return ( <>

← Documents

{d.id}} />
{d.url} }, { key: 'canonical_url', label: 'Canonical', raw: d.canonical_url }, { key: 'connector', label: 'Connector', value: {d.connector_name ?? '—'} }, { key: 'source', label: 'Source', value: {d.source_name ?? d.source_id ?? '—'} {d.source_tier !== undefined && d.source_tier !== null && } }, { key: 'doc_type', label: 'Type', raw: d.doc_type }, { key: 'entity', label: 'Entity', value: d.entity_slug && d.entity_type ? {d.entity_name ?? d.entity_slug} : — }, { key: 'status', label: 'Status', value: }, { key: 'processing', label: 'Processing', value: }, { key: 'first_seen_at', label: 'First seen', raw: d.first_seen_at ? fmtDateTime(d.first_seen_at) : null }, { key: 'last_fetched_at', label: 'Last fetched', raw: d.last_fetched_at ? fmtDateTime(d.last_fetched_at) : null }, { key: 'last_changed_at', label: 'Last changed', raw: d.last_changed_at ? fmtDateTime(d.last_changed_at) : null }, { key: 'next_fetch_at', label: 'Next fetch', raw: d.next_fetch_at ? fmtDateTime(d.next_fetch_at) : null }, { key: 'counts', label: 'Fetch / change / fail', value: {fmtInt(d.fetch_count)} / {fmtInt(d.change_count)} / {fmtInt(d.fail_count)} }, { key: 'last_status', label: 'Last HTTP', raw: d.last_status }, { key: 'etag', label: 'ETag', value: d.etag ? {d.etag} : undefined }, { key: 'content_hash', label: 'Content hash', value: d.content_hash ? {d.content_hash} : undefined }, { key: 'priority', label: 'Priority', raw: d.priority }, { key: 'needs_llm', label: 'Needs LLM', value: }, ]} />

Snapshots {snaps.length}

Observed HTTP Bytes Changed Processing Parser Transport Structured Text Run {snaps.length === 0 && No snapshots archived for this document.} {snaps.map((s) => ( {fmtDateTime(s.observed_at)} · = 400 ? 'text-danger' : ''}`}>{fmtInt(s.http_status)} {fmtBytes(s.byte_size)} v{s.parser_version ?? '?'} {s.transport ?? '—'} {s.run_id ? {s.run_id} : —} ))}
); }